/*--- CCITTOTF.C  ------------------------- Listing 10-4 -------
 * Compute CCITT-CRC on-the-fly.
 * Usage:   ccittotf filename
 *
 * Based on a similar program by Nigel Cort in C Gazette 5.1
 * (Autumn 1990).
 *------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>

#define DRIVER 1 /* DRIVER includes the file processing */

/*  Compute single-byte CRC-CCITT on-the-fly */
unsigned short GetCCITT(unsigned short crc, unsigned short ch)
{
    static unsigned int i;
    ch <<= 8;                           /* Move to MSB       */
    for (i = 8; i > 0; i--) {           /* Go through 8 bits */
        if ((ch ^ crc) & 0X8000)        /* Perform CRC calc. */
            crc = (crc << 1) ^ 0x1021;
        else
            crc <<= 1;
        ch <<= 1;
    }
    return (crc);
}

#ifdef DRIVER
int main(int argc, char * argv[])
{
   FILE *fin;            /* file we're reading into buffer */
   char *buffer;         /* buffer we're working on        */
   size_t i, j;          /* counters of bytes in buff      */
   unsigned short crc;   /* the CRC value being computed   */

   if (argc < 2) {
      fprintf(stderr, "Error! Must specify filename.\n");
      return (EXIT_FAILURE);
   }

   if ((fin = fopen(argv[1], "rb")) == NULL) {
      fprintf(stderr, "Cannot open %s", argv[1]);
      return (EXIT_FAILURE);
   }

   /*--------------------------------------------------
    * Set up a very large input buffer of 32K bytes.
    * This program does no good if it doesn't fly!
    *-------------------------------------------------*/
   if ((buffer = (char *)malloc(32766)) == NULL) {
      fprintf(stderr, "Out of memory\n");
      return (EXIT_FAILURE);
   }

   crc = 0;

   for ( ; ; ) {
      i = fread(buffer, 1, 32766, fin);
      if (i == 0) {
         if (feof(fin)) {       /* we're done, so show results */
            printf("CCITT CRC for %s is %04X\n", argv[1], crc);
            return (EXIT_SUCCESS);
         } else                 /* read another 32K of file */
            continue;
      }

      for (j = 0 ; j < i; j++)  /* loop through the buffer */
           crc = GetCCITT (crc, buffer[j]);
   }
}
#endif
